home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / jove / part07 < prev    next >
Encoding:
Internet Message Format  |  1987-02-03  |  58.9 KB

  1. Subject:  v08i026:  The JOVE text editor, Part07/13
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!rochester!jpayne (Jonathan Payne)
  6. Mod.sources: Volume 8, Issue 26
  7. Archive-name: jove/Part07
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If all goes well, you will see the message "End of archive 7 (of 13)."
  13. # Contents:  re.c recover.c scandir.c screen.c teachjove.c
  14. #   tune.template version.c
  15. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  16. echo shar: extracting "'re.c'" '(17213 characters)'
  17. if test -f 're.c' ; then 
  18.   echo shar: will not over-write existing file "'re.c'"
  19. else
  20. sed 's/^X//' >re.c <<'@//E*O*F re.c//'
  21. X/************************************************************************
  22. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  23. X * provided to you without charge, and with no warranty.  You may give  *
  24. X * away copies of JOVE, including sources, provided that this notice is *
  25. X * included in all the files.                                           *
  26. X ************************************************************************/
  27. X
  28. X/* search package */
  29. X
  30. X#include "jove.h"
  31. X#include "ctype.h"
  32. X
  33. X#define NALTS    16    /* number of alternate search strings */
  34. X
  35. Xchar    searchstr[128],
  36. X    compbuf[256],        /* global default compbuf */
  37. X    rep_search[128],    /* replace search string */
  38. X    rep_str[128],        /* contains replacement string */
  39. X    *cur_compb,        /* usually points at compbuf */
  40. X    REbuf[LBSIZE],        /* points at line we're scanning */
  41. X    *alternates[NALTS];
  42. X
  43. Xint    REdirection;
  44. X
  45. Xint    CaseIgnore = 0,
  46. X    WrapScan = 0,
  47. X    UseRE = 0;
  48. X
  49. Xprivate char    CaseEquiv[] = {
  50. X    '\000',    '\001',    '\002',    '\003',    '\004',    '\005',    '\006',    '\007',
  51. X    '\010',    '\011',    '\012',    '\013',    '\014',    '\015',    '\016',    '\017',
  52. X    '\020',    '\021',    '\022',    '\023',    '\024',    '\025',    '\026',    '\027',
  53. X    '\030',    '\031',    '\032',    '\033',    '\034',    '\035',    '\036',    '\037',
  54. X    '\040',    '!',    '"',    '#',    '$',    '%',    '&',    '\'',
  55. X    '(',    ')',    '*',    '+',    ',',    '-',    '.',    '/',
  56. X    '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
  57. X    '8',    '9',    ':',    ';',    '<',    '=',    '>',    '?',
  58. X    '@',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  59. X    'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  60. X    'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  61. X    'X',    'Y',    'Z',    '[',    '\\',    ']',    '^',    '_',
  62. X    '`',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  63. X    'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  64. X    'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  65. X    'X',    'Y',    'Z',    '{',    '|',    '}',    '~',    '\177'
  66. X};
  67. X
  68. X#define cind_cmp(a, b)    (CaseEquiv[a] == CaseEquiv[b])
  69. X
  70. Xprivate int    REpeekc;
  71. Xprivate char    *REptr;
  72. X
  73. Xprivate
  74. XREgetc()
  75. X{
  76. X    int    c;
  77. X
  78. X    if ((c = REpeekc) != -1)
  79. X        REpeekc = -1;
  80. X    else if (*REptr)
  81. X        c = *REptr++;
  82. X    else
  83. X        c = 0;
  84. X
  85. X    return c;
  86. X}
  87. X
  88. X#define STAR     01    /* Match any number of last RE. */
  89. X#define AT_BOL    2    /* ^ */
  90. X#define AT_EOL    4    /* $ */
  91. X#define AT_BOW    6    /* \< */
  92. X#define AT_EOW    8    /* \> */
  93. X#define OPENP    10    /* \( */
  94. X#define CLOSEP    12    /* \) */
  95. X#define CURLYB    14    /* \{ */
  96. X
  97. X#define NOSTR    14    /* Codes <= NOSTR can't be *'d. */
  98. X
  99. X#define ANYC    NOSTR+2        /* . */
  100. X#define NORMC    ANYC+2        /* normal character */
  101. X#define CINDC    NORMC+2        /* case independent character */
  102. X#define ONE_OF    CINDC+2        /* [xxx] */
  103. X#define NONE_OF    ONE_OF+2    /* [^xxx] */
  104. X#define BACKREF    NONE_OF+2    /* \# */
  105. X#define EOP    BACKREF+2    /* end of pattern */
  106. X
  107. X#define NPAR    9    /* [1-9] */
  108. Xprivate int    nparens;
  109. Xprivate char    *comp_p,
  110. X        **alt_p,
  111. X        **alt_endp;
  112. X
  113. XREcompile(pattern, re, into_buf, alt_bufp)
  114. Xchar    *pattern,
  115. X    *into_buf,
  116. X    **alt_bufp;
  117. X{
  118. X    REptr = pattern;
  119. X    REpeekc = -1;
  120. X    comp_p = cur_compb = into_buf;
  121. X    alt_p = alt_bufp;
  122. X    alt_endp = alt_p + NALTS;
  123. X    *alt_p++ = comp_p;
  124. X    nparens = 0;
  125. X    (void) do_comp(re ? OKAY_RE : NORM);
  126. X    *alt_p = 0;
  127. X}
  128. X
  129. X/* compile the pattern into an internal code */
  130. X
  131. Xprivate
  132. Xdo_comp(kind)
  133. X{
  134. X    char    *last_p,
  135. X        *chr_cnt = 0;
  136. X    int    parens[NPAR],
  137. X        *parenp,
  138. X        c,
  139. X        ret_code;
  140. X
  141. X    parenp = parens;
  142. X    last_p = 0;
  143. X    ret_code = 1;
  144. X
  145. X    while (c = REgetc()) {
  146. X        if (comp_p > &cur_compb[(sizeof compbuf) - 4])
  147. Xtoolong:        complain("Search string too long/complex.");
  148. X        if (c != '*')
  149. X            last_p = comp_p;
  150. X
  151. X        if (kind == NORM && index(".[*", c) != 0)
  152. X            goto defchar;
  153. X        switch (c) {
  154. X        case '\\':
  155. X            switch (c = REgetc()) {
  156. X            case 0:
  157. X                complain("Premature end of pattern.");
  158. X
  159. X            case '{':
  160. X                {
  161. X                    char    *wcntp;        /* word count */
  162. X
  163. X                    *comp_p++ = CURLYB;
  164. X                    wcntp = comp_p;
  165. X                    *comp_p++ = 0;
  166. X                    for (;;) {
  167. X                        int    comp_val;
  168. X                        char    *comp_len;
  169. X
  170. X                        comp_len = comp_p++;
  171. X                        comp_val = do_comp(IN_CB);
  172. X                        *comp_len = comp_p - comp_len;
  173. X                        (*wcntp)++;
  174. X                        if (comp_val == 0)
  175. X                            break;
  176. X                    }
  177. X                    break;
  178. X                }
  179. X
  180. X            case '}':
  181. X                if (kind != IN_CB)
  182. X                    complain("Unexpected \}.");
  183. X                ret_code = 0;
  184. X                goto outahere;
  185. X
  186. X            case '(':
  187. X                if (nparens >= NPAR)
  188. X                    complain("Too many ('s; max is %d.", NPAR);
  189. X                *comp_p++ = OPENP;
  190. X                *comp_p++ = nparens;
  191. X                *parenp++ = nparens++;
  192. X                break;
  193. X
  194. X            case ')':
  195. X                if (parenp == parens)
  196. X                    complain("Too many )'s.");
  197. X                *comp_p++ = CLOSEP;
  198. X                *comp_p++ = *--parenp;
  199. X                break;
  200. X
  201. X            case '|':
  202. X                if (alt_p >= alt_endp)
  203. X                    complain("Too many alternates; max %d.", NALTS);
  204. X                *comp_p++ = EOP;
  205. X                *alt_p++ = comp_p;
  206. X                nparens = 0;
  207. X                break;
  208. X
  209. X            case '1':
  210. X            case '2':
  211. X            case '3':
  212. X            case '4':
  213. X            case '5':
  214. X            case '6':
  215. X            case '7':
  216. X            case '8':
  217. X            case '9':
  218. X                *comp_p++ = BACKREF;
  219. X                *comp_p++ = c - '1';
  220. X                break;
  221. X
  222. X            case '<':
  223. X                *comp_p++ = AT_BOW;
  224. X                break;
  225. X
  226. X            case '>':
  227. X                *comp_p++ = AT_EOW;
  228. X                break;
  229. X
  230. X            default:
  231. X                goto defchar;
  232. X            }
  233. X            break;
  234. X
  235. X        case ',':
  236. X            if (kind != IN_CB)
  237. X                goto defchar;
  238. X            goto outahere;
  239. X
  240. X        case '.':
  241. X            *comp_p++ = ANYC;
  242. X            break;
  243. X
  244. X        case '^':
  245. X            if (comp_p == cur_compb || comp_p[-1] == EOP) {
  246. X                *comp_p++ = AT_BOL;
  247. X                break;
  248. X            }
  249. X            goto defchar;
  250. X
  251. X        case '$':
  252. X            if ((REpeekc = REgetc()) != 0 && REpeekc != '\\')
  253. X                goto defchar;
  254. X            *comp_p++ = AT_EOL;
  255. X            break;
  256. X
  257. X        case '[':
  258. X            {
  259. X                int    chrcnt;
  260. X
  261. X                *comp_p++ = ONE_OF;
  262. X            if (comp_p + 16 >= &cur_compb[(sizeof compbuf)])
  263. X                goto toolong;
  264. X                bzero(comp_p, 16);
  265. X                if ((REpeekc = REgetc()) == '^') {
  266. X                    *last_p = NONE_OF;
  267. X                    /* Get it for real this time. */
  268. X                    (void) REgetc();
  269. X                }
  270. X                chrcnt = 1;
  271. X                while ((c = REgetc()) != ']' && c != 0) {
  272. X                    if (c == '\\')
  273. X                        c = REgetc();
  274. X                else if ((REpeekc = REgetc()) == '-') {
  275. X                    int    c2;
  276. X
  277. X                    (void) REgetc();     /* reread '-' */
  278. X                    c2 = REgetc();
  279. X                    while (c < c2) {
  280. X                        comp_p[c/8] |= (1 << (c%8));
  281. X                        c++;
  282. X                    }
  283. X                }
  284. X                comp_p[c/8] |= (1 << (c%8));
  285. X                    chrcnt++;
  286. X                }
  287. X                if (c == 0)
  288. X                    complain("Missing ].");
  289. X                if (chrcnt == 1)
  290. X                    complain("Empty [].");
  291. X                comp_p += 16;
  292. X                break;
  293. X            }
  294. X
  295. X        case '*':
  296. X            if (last_p == 0 || *last_p <= NOSTR)
  297. X                goto defchar;
  298. X            if (chr_cnt) {
  299. X                char    lastc = chr_cnt[*chr_cnt];
  300. X
  301. X                comp_p = chr_cnt + *chr_cnt;
  302. X                (*chr_cnt)--;
  303. X                *comp_p++ = chr_cnt[-1] | STAR;
  304. X                *comp_p++ = lastc;
  305. X            } else
  306. X                *last_p |= STAR;
  307. X            break;
  308. X
  309. X        default:
  310. Xdefchar:        if (chr_cnt)
  311. X                (*chr_cnt)++;    /* increment the count */
  312. X            else {
  313. X                *comp_p++ = (CaseIgnore) ? CINDC : NORMC;
  314. X                chr_cnt = comp_p++;
  315. X                *chr_cnt = 1;   /* last_p[1] = 1; */
  316. X            }
  317. X            *comp_p++ = c;
  318. X            continue;
  319. X        }
  320. X        chr_cnt = FALSE;
  321. X    }
  322. Xoutahere:
  323. X    /* End of pattern, let's do some error checking. */
  324. X    if (parenp != parens)
  325. X        complain("Unmatched ()'s.");
  326. X    if (kind == IN_CB && c == 0)    /* End of pattern with \}. */
  327. X        complain("Missing \}.");
  328. X    *comp_p++ = EOP;
  329. X
  330. X    return ret_code;
  331. X}
  332. X
  333. Xprivate char    *pstrtlst[NPAR],    /* index into REbuf */
  334. X        *pendlst[NPAR],
  335. X        *REbolp,
  336. X        *locs,
  337. X        *loc1,
  338. X        *loc2;
  339. X
  340. Xint    REbom,
  341. X    REeom,        /* beginning and end of match */
  342. X    REalt_num;    /* if alternatives, which one matched? */
  343. X
  344. Xprivate
  345. Xbackref(n, linep)
  346. Xregister char    *linep;
  347. X{
  348. X    register char    *backsp,
  349. X            *backep;
  350. X
  351. X    backsp = pstrtlst[n];
  352. X    backep = pendlst[n];
  353. X    while (*backsp++ == *linep++)
  354. X        if (backsp >= backep)
  355. X            return 1;
  356. X    return 0;
  357. X}
  358. X
  359. Xprivate
  360. Xmember(comp_p, c, af)
  361. Xregister char    *comp_p;
  362. Xregister int    c,
  363. X        af;
  364. X{
  365. X    if (c == 0)
  366. X        return 0;    /* try to match EOL always fails */
  367. X    if (comp_p[c/8] & (1 << (c%8)))
  368. X        return af;
  369. X    return !af;
  370. X}
  371. X
  372. Xprivate
  373. XREmatch(linep, comp_p)
  374. Xregister char    *linep,
  375. X        *comp_p;
  376. X{
  377. X    char    *first_p = linep;
  378. X    register int    n;
  379. X
  380. X    for (;;) switch (*comp_p++) {
  381. X    case NORMC:
  382. X        n = *comp_p++;
  383. X        while (--n >= 0)
  384. X            if (*linep++ != *comp_p++)
  385. X                return 0;
  386. X        continue;
  387. X
  388. X    case CINDC:    /* case independent comparison */
  389. X        n = *comp_p++;
  390. X        while (--n >= 0)
  391. X            if (!cind_cmp(*linep++, *comp_p++))
  392. X                return 0;
  393. X        continue;
  394. X
  395. X    case EOP:
  396. X        loc2 = linep;
  397. X        REeom = (loc2 - REbolp);
  398. X        return 1;    /* Success! */
  399. X
  400. X    case AT_BOL:
  401. X        if (linep == REbolp)
  402. X            continue;
  403. X        return 0;
  404. X
  405. X    case AT_EOL:
  406. X        if (*linep == 0)
  407. X            continue;
  408. X        return 0;
  409. X
  410. X    case ANYC:
  411. X        if (*linep++ != 0)
  412. X            continue;
  413. X        return 0;
  414. X
  415. X    case AT_BOW:
  416. X        if (ismword(*linep) && (linep == REbolp || !ismword(linep[-1])))
  417. X            continue;
  418. X        return 0;
  419. X
  420. X    case AT_EOW:
  421. X        if ((*linep == 0 || !ismword(*linep)) &&
  422. X            (linep != REbolp && ismword(linep[-1])))
  423. X            continue;
  424. X        return 0;
  425. X
  426. X    case ONE_OF:
  427. X    case NONE_OF:
  428. X        if (member(comp_p, *linep++, comp_p[-1] == ONE_OF)) {
  429. X            comp_p += 16;
  430. X            continue;
  431. X        }
  432. X        return 0;
  433. X
  434. X    case OPENP:
  435. X        pstrtlst[*comp_p++] = linep;
  436. X        continue;
  437. X
  438. X    case CLOSEP:
  439. X        pendlst[*comp_p++] = linep;
  440. X        continue;
  441. X
  442. X    case BACKREF:
  443. X        if (pstrtlst[n = *comp_p++] == 0) {
  444. X            s_mess("\\%d was not specified.", n + 1);
  445. X            return 0;
  446. X        }
  447. X        if (backref(n, linep)) {
  448. X            linep += pendlst[n] - pstrtlst[n];
  449. X            continue;
  450. X        }
  451. X        return 0;
  452. X
  453. X    case CURLYB:
  454. X        {
  455. X            int    wcnt,
  456. X                any;
  457. X
  458. X            wcnt = *comp_p++;
  459. X            any = 0;
  460. X
  461. X            while (--wcnt >= 0) {
  462. X                if (any == 0)
  463. X                    any = REmatch(linep, comp_p + 1);
  464. X                comp_p += *comp_p;
  465. X            }
  466. X            if (any == 0)
  467. X                return 0;
  468. X            linep = loc2;
  469. X            continue;
  470. X        }
  471. X
  472. X    case ANYC | STAR:
  473. X        first_p = linep;
  474. X        while (*linep++)
  475. X            ;
  476. X        goto star;
  477. X
  478. X    case NORMC | STAR:
  479. X        first_p = linep;
  480. X        while (*comp_p == *linep++)
  481. X            ;
  482. X        comp_p++;
  483. X        goto star;
  484. X
  485. X    case CINDC | STAR:
  486. X        first_p = linep;
  487. X        while (cind_cmp(*comp_p, *linep++))
  488. X            ;
  489. X        comp_p++;
  490. X        goto star;
  491. X
  492. X    case ONE_OF | STAR:
  493. X    case NONE_OF | STAR:
  494. X        first_p = linep;
  495. X        while (member(comp_p, *linep++, comp_p[-1] == (ONE_OF | STAR)))
  496. X            ;
  497. X        comp_p += 16;
  498. X        goto star;
  499. X
  500. X    case BACKREF | STAR:
  501. X        first_p = linep;
  502. X        n = *comp_p++;
  503. X        while (backref(n, linep))
  504. X            linep += pendlst[n] - pstrtlst[n];
  505. X        while (linep >= first_p) {
  506. X            if (REmatch(linep, comp_p))
  507. X                return 1;
  508. X            linep -= pendlst[n] - pstrtlst[n];
  509. X        }
  510. X        continue;
  511. X
  512. Xstar:        do {
  513. X            linep--;
  514. X            if (linep < locs)
  515. X                break;
  516. X            if (REmatch(linep, comp_p))
  517. X                return 1;
  518. X        } while (linep > first_p);
  519. X        return 0;
  520. X
  521. X    default:
  522. X        complain("RE error match (%d).", comp_p[-1]);
  523. X    }
  524. X    /* NOTREACHED. */
  525. X}
  526. X
  527. Xprivate
  528. XREreset()
  529. X{
  530. X    register int    i;
  531. X
  532. X    for (i = 0; i < NPAR; i++)
  533. X        pstrtlst[i] = pendlst[i] = 0;
  534. X}
  535. X
  536. X/* Index LINE at OFFSET, the compiled EXPR, with alternates ALTS.  If
  537. X   lbuf_okay is nonzero it's okay to use linebuf if LINE is the current
  538. X   line.  This should save lots of time in things like paren matching in
  539. X   LISP mode.  Saves all that copying from linebuf to REbuf.  substitute()
  540. X   is the guy who calls re_lindex with lbuf_okay as 0, since the substitution
  541. X   gets placed in linebuf ... doesn't work too well when the source and
  542. X   destination strings are the same.  I hate all these arguments!
  543. X
  544. X   This code is cumbersome, repetetive for reasons of efficiency.  Fast
  545. X   search is a must as far as I am concerned. */
  546. X
  547. Xre_lindex(line, offset, expr, alts, lbuf_okay)
  548. XLine    *line;
  549. Xchar    *expr,
  550. X    **alts;
  551. X{
  552. X    int    isquick;
  553. X    register int    firstc,
  554. X            c;
  555. X    register char    *resp;
  556. X
  557. X    REreset();
  558. X    if (lbuf_okay) {
  559. X        REbolp = lbptr(line);
  560. X        if (offset == -1)
  561. X            offset = strlen(REbolp);    /* arg! */
  562. X    } else {
  563. X        REbolp = ltobuf(line, REbuf);
  564. X        if (offset == -1) {    /* Reverse search, find end of line. */
  565. X            extern int    Jr_Len;
  566. X
  567. X            offset = Jr_Len;    /* Just Read Len. */
  568. X        }
  569. X    }
  570. X    resp = REbolp;
  571. X    isquick = ((expr[0] == NORMC || expr[0] == CINDC) &&
  572. X           (alternates[1] == 0));
  573. X    if (isquick) {
  574. X        firstc = expr[2];
  575. X        if (expr[0] == CINDC)
  576. X            firstc = CaseEquiv[firstc];
  577. X    }
  578. X    locs = REbolp + offset;
  579. X
  580. X    if (REdirection == FORWARD) {
  581. X        do {
  582. X        char    **altp = alts;
  583. X
  584. X        if (isquick) {
  585. X            if (expr[0] == NORMC)
  586. X                while ((c = *locs++) != 0 && c != firstc)
  587. X                    ;
  588. X            else
  589. X                while (((c = *locs++) != 0) &&
  590. X                    (CaseEquiv[c] != firstc))
  591. X                    ;
  592. X            if (*--locs == 0)
  593. X                break;
  594. X        }
  595. X        REalt_num = 1;
  596. X        while (*altp) {
  597. X            if (REmatch(locs, *altp++)) {
  598. X                loc1 = locs;
  599. X                REbom = loc1 - REbolp;
  600. X                return 1;
  601. X            }
  602. X            REalt_num++;
  603. X        }
  604. X        } while (*locs++);
  605. X    } else {
  606. X        do {
  607. X        char    **altp = alts;
  608. X
  609. X        if (isquick) {
  610. X            if (expr[0] == NORMC) {
  611. X                while (locs >= REbolp && *locs-- != firstc)
  612. X                    ;
  613. X                if (*++locs != firstc)
  614. X                    break;
  615. X            } else {
  616. X                while (locs >= REbolp && CaseEquiv[*locs--] != firstc)
  617. X                    ;
  618. X                if (CaseEquiv[*++locs] != firstc)
  619. X                    break;
  620. X            }
  621. X        }
  622. X        REalt_num = 1;
  623. X        while (*altp) {
  624. X            if (REmatch(locs, *altp++)) {
  625. X                loc1 = locs;
  626. X                REbom = loc1 - REbolp;
  627. X                return 1;
  628. X            }
  629. X            REalt_num++;
  630. X        }
  631. X        } while (--locs >= resp);
  632. X    }
  633. X
  634. X    return 0;
  635. X}
  636. X
  637. Xint    okay_wrap = 0;    /* Do a wrap search ... not when we're
  638. X               parsing errors ... */
  639. X
  640. XBufpos *
  641. Xdosearch(pattern, dir, re)
  642. Xchar    *pattern;
  643. X{
  644. X    Bufpos    *pos;
  645. X
  646. X    if (bobp() && eobp())    /* Can't match!  There's no buffer. */
  647. X        return 0;
  648. X
  649. X    REcompile(pattern, re, compbuf, alternates);
  650. X
  651. X    pos = docompiled(dir, compbuf, alternates);
  652. X    return pos;
  653. X}
  654. X
  655. XBufpos *
  656. Xdocompiled(dir, expr, alts)
  657. Xchar    *expr,
  658. X    **alts;
  659. X{
  660. X    static Bufpos    ret;
  661. X    register Line    *lp;
  662. X    register int    offset;
  663. X    int    we_wrapped = 0;
  664. X
  665. X    lsave();
  666. X    /* Search now lsave()'s so it doesn't make any assumptions on
  667. X       whether the the contents of curline/curchar are in linebuf.
  668. X       Nowhere does search write all over linebuf.  However, we have to
  669. X       be careful about what calls we make here, because many of them
  670. X       assume (and rightly so) that curline is in linebuf. */
  671. X
  672. X    REdirection = dir;
  673. X    lp = curline;
  674. X    offset = curchar;
  675. X    if (dir == BACKWARD) {
  676. X        if (bobp()) {
  677. X            if (okay_wrap && WrapScan)
  678. X                goto doit;
  679. X            return 0;
  680. X        }
  681. X        /* here we simulate BackChar() */
  682. X        if (bolp()) {
  683. X            lp = lp->l_prev;
  684. X            offset = strlen(lbptr(lp));
  685. X        } else
  686. X            --offset;
  687. X    } else if ((dir == FORWARD) &&
  688. X           (lbptr(lp)[offset] == '\0') &&
  689. X           !lastp(lp)) {
  690. X        lp = lp->l_next;
  691. X        offset = 0;
  692. X    }
  693. X
  694. X    do {
  695. X        if (re_lindex(lp, offset, expr, alts, YES))
  696. X            break;
  697. Xdoit:        lp = (dir == FORWARD) ? lp->l_next : lp->l_prev;
  698. X        if (lp == 0) {
  699. X            if (okay_wrap && WrapScan) {
  700. X                lp = (dir == FORWARD) ?
  701. X                     curbuf->b_first : curbuf->b_last;
  702. X                we_wrapped++;
  703. X            } else
  704. X                 break;
  705. X        }
  706. X        if (dir == FORWARD)
  707. X            offset = 0;
  708. X        else
  709. X            offset = -1;    /* signals re_lindex ... */
  710. X    } while (lp != curline);
  711. X
  712. X    if (lp == curline && we_wrapped)
  713. X        lp = 0;
  714. X    if (lp == 0)
  715. X        return 0;
  716. X    ret.p_line = lp;
  717. X    ret.p_char = (dir == FORWARD) ? REeom : REbom;
  718. X    return &ret;
  719. X}
  720. X
  721. Xprivate char *
  722. Xinsert(off, endp, which)
  723. Xchar    *off,
  724. X    *endp;
  725. X{
  726. X    register char    *pp;
  727. X    register int    n;
  728. X
  729. X    n = pendlst[which] - pstrtlst[which];
  730. X    pp = pstrtlst[which];
  731. X    while (--n >= 0) {
  732. X        *off++ = *pp++;
  733. X        if (off >= endp)
  734. X            len_error(ERROR);
  735. X    }
  736. X    return off;
  737. X}
  738. X
  739. X/* Perform the substitution.  If DELP is nonzero the matched string is
  740. X   deleted, i.e., the substitution string is not inserted. */
  741. X
  742. Xre_dosub(tobuf, delp)
  743. Xchar    *tobuf;
  744. X{
  745. X    register char    *tp,
  746. X            *rp,
  747. X            *repp;
  748. X    int    c;
  749. X    char    *endp;
  750. X
  751. X    tp = tobuf;
  752. X    endp = tp + LBSIZE;
  753. X    rp = REbuf;
  754. X    repp = rep_str;
  755. X
  756. X    while (rp < loc1)
  757. X        *tp++ = *rp++;
  758. X
  759. X    if (!delp) while (c = *repp++) {
  760. X        if (c == '\\') {
  761. X            if ((c = *repp++) == '\0') {
  762. X                *tp++ = '\\';
  763. X                  goto endchk;
  764. X            } else if ((c = *repp++) >= '1' && c <= nparens + '1') {
  765. X                tp = insert(tp, endp, c - '1');
  766. X                continue;
  767. X            }
  768. X        }
  769. X        *tp++ = c;
  770. Xendchk:        if (tp >= endp)
  771. X            len_error(ERROR);
  772. X    }
  773. X    rp = loc2;
  774. X    loc2 = REbuf + max(1, tp - tobuf);
  775. X    REeom = loc2 - REbuf;
  776. X    /* At least one character past the match, to prevent an infinite
  777. X       number of replacements in the same position, e.g.,
  778. X       replace "^" with "". */
  779. X    while (*tp++ = *rp++)
  780. X        if (tp >= endp)
  781. X            len_error(ERROR);
  782. X}
  783. X
  784. Xputmatch(which, buf, size)
  785. Xchar    *buf;
  786. X{
  787. X    *(insert(buf, buf + size, which - 1)) = 0;
  788. X}
  789. X
  790. Xsetsearch(str)
  791. Xchar    *str;
  792. X{
  793. X    strcpy(searchstr, str);
  794. X}
  795. X
  796. Xchar *
  797. Xgetsearch()
  798. X{
  799. X    return searchstr;
  800. X}
  801. X
  802. XRErecur()
  803. X{
  804. X    char    sbuf[sizeof searchstr],
  805. X        cbuf[sizeof compbuf],
  806. X        repbuf[sizeof rep_str],
  807. X        *altbuf[NALTS];
  808. X    int    npars;
  809. X    Mark    *m = MakeMark(curline, REbom, FLOATER);
  810. X
  811. X    message("Type C-X C-C to continue with query replace.");
  812. X
  813. X    npars = nparens;
  814. X    byte_copy(compbuf, cbuf, sizeof compbuf);
  815. X    byte_copy(searchstr, sbuf, sizeof searchstr);
  816. X    byte_copy(rep_str, repbuf, sizeof rep_str);
  817. X    byte_copy((char *) alternates, (char *) altbuf, sizeof alternates);
  818. X    Recur();
  819. X    nparens = npars;
  820. X    byte_copy(cbuf, compbuf, sizeof compbuf);
  821. X    byte_copy(sbuf, searchstr, sizeof searchstr);
  822. X    byte_copy(repbuf, rep_str, sizeof rep_str);
  823. X    byte_copy((char *) altbuf, (char *) alternates, sizeof alternates);
  824. X    if (!exp_p)
  825. X        ToMark(m);
  826. X    DelMark(m);
  827. X}
  828. X
  829. XForSearch()
  830. X{
  831. X    search(FORWARD, UseRE, YES);
  832. X}
  833. X
  834. XRevSearch()
  835. X{
  836. X    search(BACKWARD, UseRE, YES);
  837. X}
  838. X
  839. XFSrchND()
  840. X{
  841. X    search(FORWARD, UseRE, NO);
  842. X}
  843. X
  844. XRSrchND()
  845. X{
  846. X    search(BACKWARD, UseRE, NO);
  847. X}
  848. X
  849. Xprivate
  850. Xsearch(dir, re, setdefault)
  851. X{
  852. X    Bufpos    *newdot;
  853. X    char    *s;
  854. X
  855. X    s = ask(searchstr, ProcFmt);
  856. X    if (setdefault)
  857. X        setsearch(s);
  858. X    okay_wrap = YES;
  859. X    newdot = dosearch(s, dir, re);
  860. X    okay_wrap = NO;
  861. X    if (newdot == 0) {
  862. X        if (WrapScan)
  863. X            complain("No \"%s\" in buffer.", s);
  864. X        else
  865. X            complain("No \"%s\" found to %s.", s,
  866. X                 (dir == FORWARD) ? "bottom" : "top");
  867. X    }
  868. X    PushPntp(newdot->p_line);
  869. X    SetDot(newdot);
  870. X}
  871. X
  872. X/* Do we match PATTERN at OFFSET in BUF? */
  873. X
  874. XLookingAt(pattern, buf, offset)
  875. Xchar    *pattern,
  876. X    *buf;
  877. X{
  878. X    register char    **alt = alternates;
  879. X
  880. X    REcompile(pattern, 1, compbuf, alternates);
  881. X    REreset();
  882. X    locs = buf + offset;
  883. X    REbolp = buf;
  884. X
  885. X    while (*alt)
  886. X        if (REmatch(locs, *alt++))
  887. X            return 1;
  888. X    return 0;
  889. X}
  890. X
  891. Xlook_at(expr)
  892. Xchar    *expr;
  893. X{
  894. X    REcompile(expr, 0, compbuf, alternates);
  895. X    REreset();
  896. X    locs = linebuf + curchar;
  897. X    REbolp = linebuf;
  898. X    if (REmatch(locs, alternates[0]))
  899. X        return 1;
  900. X    return 0;
  901. X}
  902. X
  903. @//E*O*F re.c//
  904. if test 17213 -ne "`wc -c <'re.c'`"; then
  905.     echo shar: error transmitting "'re.c'" '(should have been 17213 characters)'
  906. fi
  907. fi # end of overwriting check
  908. echo shar: extracting "'recover.c'" '(14068 characters)'
  909. if test -f 'recover.c' ; then 
  910.   echo shar: will not over-write existing file "'recover.c'"
  911. else
  912. sed 's/^X//' >recover.c <<'@//E*O*F recover.c//'
  913. X/************************************************************************
  914. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  915. X * provided to you without charge, and with no warranty.  You may give  *
  916. X * away copies of JOVE, including sources, provided that this notice is *
  917. X * included in all the files.                                           *
  918. X ************************************************************************/
  919. X
  920. X/* Recovers JOVE files after a system/editor crash.
  921. X   Usage: recover [-d directory] [-syscrash]
  922. X   The -syscrash option is specified in /etc/rc and what it does it
  923. X   move all the jove tmp files from TMP_DIR to REC_DIR.
  924. X
  925. X   The -d option lets you specify the directory to search for tmp files when
  926. X   the default isn't the right one.
  927. X
  928. X   Look in Makefile to change the default directories. */
  929. X
  930. X#include <stdio.h>    /* Do stdio first so it doesn't override OUR
  931. X               definitions. */
  932. X#undef EOF
  933. X#undef BUFSIZ
  934. X#undef putchar
  935. X
  936. X#include "jove.h"
  937. X#include "temp.h"
  938. X#include "rec.h"
  939. X#include <signal.h>
  940. X#include <sys/file.h>
  941. X#include <sys/stat.h>
  942. X#include <sys/dir.h>
  943. X
  944. X#ifndef L_SET
  945. X#    define L_SET    0
  946. X#    define L_INCR    1
  947. X#endif
  948. X
  949. Xchar    blk_buf[BUFSIZ];
  950. Xint    nleft;
  951. XFILE    *ptrs_fp;
  952. Xint    data_fd;
  953. Xstruct rec_head    Header;
  954. Xchar    datafile[40],
  955. X    pntrfile[40];
  956. Xlong    Nchars,
  957. X    Nlines;
  958. Xchar    tty[] = "/dev/tty";
  959. Xint    UserID,
  960. X    Verbose = 0;
  961. Xchar    *Directory = 0;        /* the directory we're looking in */
  962. X
  963. Xstruct file_pair {
  964. X    char    *file_data,
  965. X        *file_rec;
  966. X#define INSPECTED    01
  967. X    int    file_flags;
  968. X    struct file_pair    *file_next;
  969. X} *First = 0,
  970. X  *Last = 0;
  971. X
  972. Xstruct rec_entry    *buflist[100] = {0};
  973. X
  974. X#ifndef BSD4_2
  975. X
  976. Xtypedef struct {
  977. X    int    d_fd;        /* File descriptor for this directory */
  978. X} DIR;
  979. X
  980. XDIR *
  981. Xopendir(dir)
  982. Xchar    *dir;
  983. X{
  984. X    DIR    *dp = (DIR *) malloc(sizeof *dp);
  985. X
  986. X    if ((dp->d_fd = open(dir, 0)) == -1)
  987. X        return NULL;
  988. X    return dp;
  989. X}
  990. X
  991. Xclosedir(dp)
  992. XDIR    *dp;
  993. X{
  994. X    (void) close(dp->d_fd);
  995. X    free(dp);
  996. X}
  997. X
  998. Xstruct direct *
  999. Xreaddir(dp)
  1000. XDIR    *dp;
  1001. X{
  1002. X    static struct direct    dir;
  1003. X
  1004. X    do
  1005. X        if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
  1006. X            return NULL;
  1007. X    while (dir.d_ino == 0);
  1008. X
  1009. X    return &dir;
  1010. X}
  1011. X
  1012. X#endif BSD4_2
  1013. X
  1014. X/* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
  1015. X   long. */
  1016. X
  1017. Xgetline(tl, buf)
  1018. Xdisk_line    tl;
  1019. Xchar    *buf;
  1020. X{
  1021. X    register char    *bp,
  1022. X            *lp;
  1023. X    register int    nl;
  1024. X    char    *getblock();
  1025. X
  1026. X    lp = buf;
  1027. X    bp = getblock(tl >> 1);
  1028. X    nl = nleft;
  1029. X    tl = blk_round(tl);
  1030. X
  1031. X    while (*lp++ = *bp++) {
  1032. X        if (--nl == 0) {
  1033. X            tl = forward_block(tl);
  1034. X            bp = getblock(tl >> 1);
  1035. X            nl = nleft;
  1036. X        }
  1037. X    }
  1038. X}
  1039. X
  1040. Xchar *
  1041. Xgetblock(atl)
  1042. Xdisk_line    atl;
  1043. X{
  1044. X    int    bno,
  1045. X        off;
  1046. X    static int    curblock = -1;
  1047. X
  1048. X    bno = daddr_to_bno(atl);
  1049. X    off = daddr_to_off(atl);
  1050. X    nleft = BUFSIZ - off;
  1051. X
  1052. X    if (bno != curblock) {
  1053. X        lseek(data_fd, (long) bno * BUFSIZ, L_SET);
  1054. X        read(data_fd, blk_buf, BUFSIZ);
  1055. X        curblock = bno;
  1056. X    }
  1057. X    return blk_buf + off;
  1058. X}
  1059. X
  1060. Xchar *
  1061. Xcopystr(s)
  1062. Xchar    *s;
  1063. X{
  1064. X    char    *str;
  1065. X
  1066. X    str = malloc(strlen(s) + 1);
  1067. X    strcpy(str, s);
  1068. X
  1069. X    return str;
  1070. X}
  1071. X
  1072. X/* Scandir returns the number of entries or -1 if the directory cannoot
  1073. X   be opened or malloc fails. */
  1074. X
  1075. Xscandir(dir, nmptr, qualify, sorter)
  1076. Xchar    *dir;
  1077. Xstruct direct    ***nmptr;
  1078. Xint    (*qualify)();
  1079. Xstruct direct    *(*sorter)();
  1080. X{
  1081. X    DIR    *dirp;
  1082. X    struct direct    *entry,
  1083. X            **ourarray;
  1084. X    int    nalloc = 10,
  1085. X        nentries = 0;
  1086. X
  1087. X    if ((dirp = opendir(dir)) == NULL)
  1088. X        return -1;
  1089. X    ourarray = (struct direct **) malloc(nalloc * sizeof (struct direct *));
  1090. X    while ((entry = readdir(dirp)) != NULL) {
  1091. X        if (qualify != 0 && (*qualify)(entry) == 0)
  1092. X            continue;
  1093. X        if (nentries == nalloc) {
  1094. X            ourarray = (struct direct **) realloc(ourarray, (nalloc += 10) * sizeof (struct direct));
  1095. X            if (ourarray == NULL)
  1096. X                return -1;
  1097. X        }
  1098. X        ourarray[nentries] = (struct direct *) malloc(sizeof *entry);
  1099. X        *ourarray[nentries] = *entry;
  1100. X        nentries++;
  1101. X    }
  1102. X    closedir(dirp);
  1103. X    if (nentries != nalloc)
  1104. X        ourarray = (struct direct **) realloc(ourarray,
  1105. X                    (nentries * sizeof (struct direct)));
  1106. X    if (sorter != 0)
  1107. X        qsort(ourarray, nentries, sizeof (struct direct **), sorter);
  1108. X    *nmptr = ourarray;
  1109. X
  1110. X    return nentries;
  1111. X}
  1112. X
  1113. Xalphacomp(a, b)
  1114. Xstruct direct    **a,
  1115. X        **b;
  1116. X{
  1117. X    return strcmp((*a)->d_name, (*b)->d_name);
  1118. X}
  1119. X
  1120. Xchar    *CurDir;
  1121. X
  1122. X/* Scan the DIRNAME directory for jove tmp files, and make a linked list
  1123. X   out of them. */
  1124. X
  1125. Xget_files(dirname)
  1126. Xchar    *dirname;
  1127. X{
  1128. X    int    add_name();
  1129. X    struct direct    **nmptr;
  1130. X
  1131. X    CurDir = dirname;
  1132. X    scandir(dirname, &nmptr, add_name, (int (*)())0);
  1133. X}
  1134. X
  1135. Xadd_name(dp)
  1136. Xstruct direct    *dp;
  1137. X{
  1138. X    char    dfile[128],
  1139. X        rfile[128];
  1140. X    struct file_pair    *fp;
  1141. X    struct rec_head        header;
  1142. X    int    fd;
  1143. X
  1144. X    if (strncmp(dp->d_name, "jrec", 4) != 0)
  1145. X        return 0;
  1146. X    /* If we get here, we found a "recover" tmp file, so now
  1147. X       we look for the corresponding "data" tmp file.  First,
  1148. X       though, we check to see whether there is anything in
  1149. X       the "recover" file.  If it's 0 length, there's no point
  1150. X       in saving its name. */
  1151. X    (void) sprintf(rfile, "%s/%s", CurDir, dp->d_name);
  1152. X    (void) sprintf(dfile, "%s/jove%s", CurDir, dp->d_name + 4);
  1153. X    if ((fd = open(rfile, 0)) != -1) {
  1154. X        if ((read(fd, (char *) &header, sizeof header) != sizeof header)) {
  1155. X            close(fd);
  1156. X                return 0;
  1157. X        } else
  1158. X            close(fd);
  1159. X    }
  1160. X    if (access(dfile, 0) != 0) {
  1161. X        fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, dp->d_name);
  1162. X        fprintf(stderr, "so deleting...\n");
  1163. X        (void) unlink(rfile);
  1164. X        (void) unlink(dfile);
  1165. X        return 0;
  1166. X    }
  1167. X    /* If we get here, we've found both files, so we put them
  1168. X       in the list. */
  1169. X    fp = (struct file_pair *) malloc (sizeof *fp);
  1170. X    if ((char *) fp == 0) {
  1171. X        fprintf(stderr, "recover: cannot malloc for file_pair.\n");
  1172. X        exit(-1);
  1173. X    }
  1174. X    fp->file_data = copystr(dfile);
  1175. X    fp->file_rec = copystr(rfile);
  1176. X    fp->file_flags = 0;
  1177. X    fp->file_next = First;
  1178. X    First = fp;
  1179. X
  1180. X    return 1;
  1181. X}
  1182. X
  1183. Xoptions()
  1184. X{
  1185. X    printf("Options are:\n");
  1186. X    printf("    ?        list options.\n");
  1187. X    printf("    get        get a buffer to a file.\n");
  1188. X    printf("    list        list known buffers.\n");
  1189. X    printf("    print        print a buffer to terminal.\n");
  1190. X    printf("    quit        quit and delete jove tmp files.\n");
  1191. X    printf("    restore        restore all buffers.\n");
  1192. X}
  1193. X
  1194. X/* Returns a legitimate buffer # */
  1195. X
  1196. Xstruct rec_entry **
  1197. Xgetsrc()
  1198. X{
  1199. X    char    name[128];
  1200. X    int    number;
  1201. X
  1202. X    for (;;) {
  1203. X        tellme("Which buffer ('?' for list)? ", name);
  1204. X        if (name[0] == '?')
  1205. X            list();
  1206. X        else if (name[0] == '\0')
  1207. X            return 0;
  1208. X        else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers)
  1209. X            return &buflist[number];
  1210. X        else {
  1211. X            int    i;
  1212. X
  1213. X            for (i = 1; i <= Header.Nbuffers; i++)
  1214. X                if (strcmp(buflist[i]->r_bname, name) == 0)
  1215. X                    return &buflist[i];
  1216. X            printf("%s: unknown buffer.\n", name);
  1217. X        }
  1218. X    }
  1219. X}
  1220. X
  1221. X/* Get a destination file name. */
  1222. X
  1223. Xstatic char *
  1224. Xgetdest()
  1225. X{
  1226. X    static char    filebuf[256];
  1227. X
  1228. X    tellme("Output file: ", filebuf);
  1229. X    if (filebuf[0] == '\0')
  1230. X        return 0;
  1231. X    return filebuf;
  1232. X}
  1233. X
  1234. X#include "ctype.h"
  1235. X
  1236. Xchar *
  1237. Xreadword(buf)
  1238. Xchar    *buf;
  1239. X{
  1240. X    int    c;
  1241. X    char    *bp = buf;
  1242. X
  1243. X    while (index(" \t\n", c = getchar()))
  1244. X        ;
  1245. X
  1246. X    do {
  1247. X        if (index(" \t\n", c))
  1248. X            break;
  1249. X        *bp++ = c;
  1250. X    } while ((c = getchar()) != EOF);
  1251. X    *bp = 0;
  1252. X
  1253. X    return buf;
  1254. X}
  1255. X
  1256. Xtellme(quest, answer)
  1257. Xchar    *quest,
  1258. X    *answer;
  1259. X{
  1260. X    if (stdin->_cnt <= 0) {
  1261. X        printf("%s", quest);
  1262. X        fflush(stdout);
  1263. X    }
  1264. X    readword(answer);
  1265. X}
  1266. X
  1267. X/* Print the specified file to strandard output. */
  1268. X
  1269. Xjmp_buf    int_env;
  1270. X
  1271. Xcatch()
  1272. X{
  1273. X    longjmp(int_env, 1);
  1274. X}
  1275. X
  1276. Xrestore()
  1277. X{
  1278. X    register int    i;
  1279. X    char    tofile[100],
  1280. X        answer[30];
  1281. X    int    nrecovered = 0;
  1282. X
  1283. X    for (i = 1; i <= Header.Nbuffers; i++) {
  1284. X        (void) sprintf(tofile, "#%s", buflist[i]->r_bname);
  1285. Xtryagain:
  1286. X        printf("Restoring %s to %s, okay?", buflist[i]->r_bname,
  1287. X                             tofile);
  1288. X        tellme(" ", answer);
  1289. X        switch (answer[0]) {
  1290. X        case 'y':
  1291. X            break;
  1292. X
  1293. X        case 'n':
  1294. X            continue;
  1295. X
  1296. X        default:
  1297. X            tellme("What file should I use instead? ", tofile);
  1298. X            goto tryagain;
  1299. X        }
  1300. X        get(&buflist[i], tofile);
  1301. X        nrecovered++;
  1302. X    }
  1303. X    printf("Recovered %d buffers.\n", nrecovered);
  1304. X}
  1305. X
  1306. Xget(src, dest)
  1307. Xstruct rec_entry    **src;
  1308. Xchar    *dest;
  1309. X{
  1310. X    FILE    *outfile;
  1311. X
  1312. X    if (src == 0 || dest == 0)
  1313. X        return;
  1314. X    (void) signal(SIGINT, catch);
  1315. X    if (setjmp(int_env) == 0) {
  1316. X        if ((outfile = fopen(dest, "w")) == NULL) {
  1317. X            printf("recover: cannot create %s.\n", dest);
  1318. X            return;
  1319. X        }
  1320. X        seekto(src - buflist);
  1321. X        if (dest != tty)
  1322. X            printf("\"%s\"", dest);
  1323. X        dump_file(outfile);
  1324. X    } else
  1325. X        printf("\nAborted!\n");
  1326. X    fclose(outfile);
  1327. X    if (dest != tty)
  1328. X        printf(" %ld lines, %ld characters.\n", Nlines, Nchars);
  1329. X    (void) signal(SIGINT, SIG_DFL);
  1330. X}
  1331. X
  1332. Xchar **
  1333. Xscanvec(args, str)
  1334. Xregister char    **args,
  1335. X        *str;
  1336. X{
  1337. X    while (*args) {
  1338. X        if (strcmp(*args, str) == 0)
  1339. X            return args;
  1340. X        args++;
  1341. X    }
  1342. X    return 0;
  1343. X}
  1344. X
  1345. Xread_rec(recptr)
  1346. Xstruct rec_entry    *recptr;
  1347. X{
  1348. X    if (fread((char *) recptr, sizeof *recptr, 1, ptrs_fp) != 1)
  1349. X        fprintf(stderr, "recover: cannot read record.\n");
  1350. X}
  1351. X
  1352. Xseekto(which)
  1353. X{
  1354. X    struct rec_entry    rec;
  1355. X
  1356. X    fseek(ptrs_fp, (long) (sizeof Header), L_SET);
  1357. X    
  1358. X    while (which-- > 1) {
  1359. X        read_rec(&rec);
  1360. X        if (fseek(ptrs_fp, (long) rec.r_nlines * sizeof (disk_line),
  1361. X            L_INCR) == -1)
  1362. X            printf("recover: improper fseek!\n");
  1363. X    }
  1364. X}
  1365. X
  1366. Xmakblist()
  1367. X{
  1368. X    int    i;
  1369. X
  1370. X    for (i = 1; i <= Header.Nbuffers; i++) {
  1371. X        seekto(i);
  1372. X        if (buflist[i] == 0)
  1373. X            buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry));
  1374. X        read_rec(buflist[i]);
  1375. X    }
  1376. X    if (buflist[i]) {
  1377. X        free((char *) buflist[i]);
  1378. X        buflist[i] = 0;
  1379. X    }
  1380. X}
  1381. X
  1382. Xdisk_line
  1383. Xgetaddr(fp)
  1384. Xregister FILE    *fp;
  1385. X{
  1386. X    register int    nchars = sizeof (disk_line);
  1387. X    disk_line    addr;
  1388. X    register char    *cp = (char *) &addr;
  1389. X
  1390. X    while (--nchars >= 0)
  1391. X        *cp++ = getc(fp);
  1392. X
  1393. X    return addr;
  1394. X}
  1395. X
  1396. Xdump_file(out)
  1397. XFILE    *out;
  1398. X{
  1399. X    struct rec_entry    record;
  1400. X    register int    nlines;
  1401. X    register disk_line    daddr;
  1402. X    char    buf[BUFSIZ];
  1403. X
  1404. X    read_rec(&record);
  1405. X    nlines = record.r_nlines;
  1406. X    Nchars = Nlines = 0L;
  1407. X    while (--nlines >= 0) {
  1408. X        daddr = getaddr(ptrs_fp);
  1409. X        getline(daddr, buf);
  1410. X        Nlines++;
  1411. X        Nchars += 1 + strlen(buf);
  1412. X        fputs(buf, out);
  1413. X        if (nlines > 0)
  1414. X            fputc('\n', out);
  1415. X    }
  1416. X    if (out != stdout)
  1417. X        fclose(out);
  1418. X}
  1419. X
  1420. X/* List all the buffers. */
  1421. X
  1422. Xlist()
  1423. X{
  1424. X    int    i;
  1425. X
  1426. X    for (i = 1; i <= Header.Nbuffers; i++)
  1427. X        printf("%d) buffer %s  \"%s\" (%d lines)\n", i,
  1428. X            buflist[i]->r_bname,
  1429. X            buflist[i]->r_fname,
  1430. X            buflist[i]->r_nlines);
  1431. X}
  1432. X
  1433. Xdoit(fp)
  1434. Xstruct file_pair    *fp;
  1435. X{
  1436. X    char    answer[30];
  1437. X    char    *datafile = fp->file_data,
  1438. X        *pntrfile = fp->file_rec;
  1439. X
  1440. X    ptrs_fp = fopen(pntrfile, "r");
  1441. X    if (ptrs_fp == NULL) {
  1442. X        if (Verbose)
  1443. X            fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile);
  1444. X        return 0;
  1445. X    }
  1446. X    fread((char *) &Header, sizeof Header, 1, ptrs_fp);
  1447. X    if (Header.Uid != UserID)
  1448. X        return 0;
  1449. X
  1450. X    /* Don't ask about JOVE's that are still running ... */
  1451. X#ifdef KILL0
  1452. X    if (kill(Header.Pid, 0) == 0)
  1453. X        return 0;
  1454. X#else
  1455. X#ifdef LSRHS
  1456. X    if (pexist(Header.Pid))
  1457. X        return 0;
  1458. X#endif LSRHS
  1459. X#endif KILL0
  1460. X
  1461. X    if (Header.Nbuffers == 0) {
  1462. X        printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile);
  1463. X        ask_del(" ", fp);
  1464. X        return 1;
  1465. X    }
  1466. X        
  1467. X    if (Header.Nbuffers < 0) {
  1468. X        fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile);
  1469. X        ask_del("Should I delete it? ", fp);
  1470. X        return 1;    /* We'll, we sort of found something. */
  1471. X    }
  1472. X    printf("Found %d buffer%s last updated: %s",
  1473. X        Header.Nbuffers,
  1474. X        Header.Nbuffers != 1 ? "s" : "",
  1475. X        ctime(&Header.UpdTime));
  1476. X    data_fd = open(datafile, 0);
  1477. X    if (data_fd == -1) {
  1478. X        fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile);
  1479. X        ask_del("Should I delete the tmp files? ", fp);
  1480. X        return 1;
  1481. X    }
  1482. X    makblist();
  1483. X
  1484. X    for (;;) {
  1485. X        tellme("(Type '?' for options): ", answer);
  1486. X        switch (answer[0]) {
  1487. X        case '\0':
  1488. X            continue;
  1489. X
  1490. X        case '?':
  1491. X            options();
  1492. X            break;
  1493. X
  1494. X        case 'l':
  1495. X            list();
  1496. X            break;
  1497. X
  1498. X        case 'p':
  1499. X            get(getsrc(), tty);
  1500. X            break;
  1501. X
  1502. X        case 'q':
  1503. X            ask_del("Shall I delete the tmp files? ", fp);
  1504. X            return 1;
  1505. X
  1506. X        case 'g':
  1507. X            {    /* So it asks for src first. */
  1508. X                char    *dest;
  1509. X                struct rec_entry    **src;
  1510. X
  1511. X                if ((src = getsrc()) == 0)
  1512. X                    break;
  1513. X                dest = getdest();
  1514. X            get(src, dest);
  1515. X            break;
  1516. X            }
  1517. X
  1518. X        case 'r':
  1519. X            restore();
  1520. X            break;
  1521. X
  1522. X        default:
  1523. X            printf("I don't know how to \"%s\"!\n", answer);
  1524. X            break;
  1525. X        }
  1526. X    }
  1527. X}
  1528. X
  1529. Xask_del(prompt, fp)
  1530. Xchar    *prompt;
  1531. Xstruct file_pair    *fp;
  1532. X{
  1533. X    char    yorn[20];
  1534. X
  1535. X    tellme(prompt, yorn);
  1536. X    if (yorn[0] == 'y')
  1537. X        del_files(fp);
  1538. X}
  1539. X
  1540. Xdel_files(fp)
  1541. Xstruct file_pair    *fp;
  1542. X{
  1543. X    (void) unlink(fp->file_data);
  1544. X    (void) unlink(fp->file_rec);
  1545. X}
  1546. X
  1547. X#ifdef notdef
  1548. Xsavetmps()
  1549. X{
  1550. X    struct file_pair    *fp;
  1551. X    int    status,
  1552. X        pid;
  1553. X
  1554. X    if (strcmp(TMP_DIR, REC_DIR) == 0)
  1555. X        return;        /* Files are moved to the same place. */
  1556. X    get_files(TMP_DIR);
  1557. X    for (fp = First; fp != 0; fp = fp->file_next) {
  1558. X        switch (pid = fork()) {
  1559. X        case -1:
  1560. X            fprintf(stderr, "recover: can't fork\n!");
  1561. X            exit(-1);
  1562. X
  1563. X        case 0:
  1564. X            execl("/bin/cp", "cp", fp->file_data, fp->file_rec, 
  1565. X                  REC_DIR, (char *)0);
  1566. X            fprintf(stderr, "recover: cannot execl /bin/cp.\n");
  1567. X            exit(-1);
  1568. X
  1569. X        default:
  1570. X            while (wait(&status) != pid)
  1571. X                ;
  1572. X            if (status != 0)
  1573. X                fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status);
  1574. X        }
  1575. X    }
  1576. X}
  1577. X#endif
  1578. X
  1579. Xlookup(dir)
  1580. Xchar    *dir;
  1581. X{
  1582. X    struct file_pair    *fp;
  1583. X    struct rec_head        header;
  1584. X    char    yorn[20];
  1585. X    int    nfound = 0,
  1586. X        this_one;
  1587. X
  1588. X    printf("Checking %s ...\n", dir);
  1589. X    Directory = dir;
  1590. X    get_files(dir);
  1591. X    for (fp = First; fp != 0; fp = fp->file_next) {
  1592. X        nfound += doit(fp);
  1593. X        if (ptrs_fp)
  1594. X            (void) fclose(ptrs_fp);
  1595. X        if (data_fd > 0)
  1596. X            (void) close(data_fd);
  1597. X    }
  1598. X    return nfound;
  1599. X}
  1600. X
  1601. Xmain(argc, argv)
  1602. Xint    argc;
  1603. Xchar    *argv[];
  1604. X{
  1605. X    int    nfound;
  1606. X    char    **argvp;
  1607. X
  1608. X    UserID = getuid();
  1609. X
  1610. X    if (scanvec(argv, "-help")) {
  1611. X        printf("recover: usage: recover [-d directory]\n");
  1612. X        printf("Use \"recover\" after JOVE has died for some\n");
  1613. X        printf("unknown reason.\n\n");
  1614. X        printf("Use \"recover -syscrash\" when the system is in the process\n");
  1615. X        printf("of rebooting.  This is done automatically at reboot time\n");
  1616. X        printf("and so most of you don't have to worry about that.\n\n");
  1617. X        printf("Use \"recover -d directory\" when the tmp files are store\n");
  1618. X        printf("in DIRECTORY instead of the default one (/tmp).\n");
  1619. X        exit(0);
  1620. X    }
  1621. X    if (scanvec(argv, "-v"))
  1622. X        Verbose++;
  1623. X/*    if (scanvec(argv, "-syscrash")) {
  1624. X        printf("Recovering jove files ... ");
  1625. X        savetmps();
  1626. X        printf("Done.\n");
  1627. X        exit(0);
  1628. X    } */
  1629. X    if (argvp = scanvec(argv, "-uid"))
  1630. X        UserID = atoi(argvp[1]);
  1631. X    if (argvp = scanvec(argv, "-d"))
  1632. X        nfound = lookup(argvp[1]);
  1633. X    else
  1634. X        nfound = lookup(TmpFilePath);
  1635. X    if (nfound == 0)
  1636. X        printf("There's nothing to recover.\n");
  1637. X}
  1638. @//E*O*F recover.c//
  1639. if test 14068 -ne "`wc -c <'recover.c'`"; then
  1640.     echo shar: error transmitting "'recover.c'" '(should have been 14068 characters)'
  1641. fi
  1642. fi # end of overwriting check
  1643. echo shar: extracting "'scandir.c'" '(2708 characters)'
  1644. if test -f 'scandir.c' ; then 
  1645.   echo shar: will not over-write existing file "'scandir.c'"
  1646. else
  1647. sed 's/^X//' >scandir.c <<'@//E*O*F scandir.c//'
  1648. X/************************************************************************
  1649. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1650. X * provided to you without charge, and with no warranty.  You may give  *
  1651. X * away copies of JOVE, including sources, provided that this notice is *
  1652. X * included in all the files.                                           *
  1653. X ************************************************************************/
  1654. X
  1655. X#include "jove.h"
  1656. X#include <sys/stat.h>
  1657. X#include <sys/dir.h>
  1658. X
  1659. X#ifdef F_COMPLETION
  1660. X
  1661. X#ifdef BSD4_2
  1662. X
  1663. X#define DIRSIZE(entry)    DIRSIZ(entry)
  1664. X
  1665. X#else
  1666. X
  1667. X#define DIRSIZE(entry)    (min(strlen(entry->d_name), DIRSIZ))
  1668. X
  1669. Xtypedef struct {
  1670. X    int    d_fd;        /* File descriptor for this directory */
  1671. X} DIR;
  1672. X
  1673. XDIR *
  1674. Xopendir(dir)
  1675. Xchar    *dir;
  1676. X{
  1677. X    DIR    *dp = (DIR *) malloc(sizeof *dp);
  1678. X    struct stat    stbuf;
  1679. X
  1680. X    if ((dp->d_fd = open(dir, 0)) == -1)
  1681. X        return 0;
  1682. X    if ((fstat(dp->d_fd, &stbuf) == -1) || !(stbuf.st_mode & S_IFDIR)) {
  1683. X        closedir(dp);
  1684. X        return 0;    /* this isn't a directory! */
  1685. X    }
  1686. X    return dp;
  1687. X}
  1688. X
  1689. Xclosedir(dp)
  1690. XDIR    *dp;
  1691. X{
  1692. X    (void) close(dp->d_fd);
  1693. X    free((char *) dp);
  1694. X}
  1695. X
  1696. Xstruct direct *
  1697. Xreaddir(dp)
  1698. XDIR    *dp;
  1699. X{
  1700. X    static struct direct    dir;
  1701. X
  1702. X    do
  1703. X        if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
  1704. X            return 0;
  1705. X    while (dir.d_ino == 0);
  1706. X
  1707. X    return &dir;
  1708. X}
  1709. X
  1710. X#endif BSD4_2
  1711. X
  1712. X/* Scandir returns the number of entries or -1 if the directory cannoot
  1713. X   be opened or malloc fails. */
  1714. X
  1715. Xscandir(dir, nmptr, qualify, sorter)
  1716. Xchar    *dir;
  1717. Xchar    ***nmptr;
  1718. Xint    (*qualify)();
  1719. Xint    (*sorter)();
  1720. X{
  1721. X    DIR    *dirp;
  1722. X    struct direct    *entry;
  1723. X    char    **ourarray;
  1724. X    unsigned int    nalloc = 10,
  1725. X            nentries = 0;
  1726. X
  1727. X    if ((dirp = opendir(dir)) == 0)
  1728. X        return -1;
  1729. X    if ((ourarray = (char **) malloc(nalloc * sizeof (char *))) == 0)
  1730. Xmemfail:    complain("[Malloc failed: cannot scandir]");
  1731. X    while ((entry = readdir(dirp)) != 0) {
  1732. X        if (qualify != 0 && (*qualify)(entry->d_name) == 0)
  1733. X            continue;
  1734. X        if (nentries == nalloc) {
  1735. X            ourarray = (char **) realloc((char *) ourarray, (nalloc += 10) * sizeof (char *));
  1736. X            if (ourarray == 0)
  1737. X                goto memfail;
  1738. X        }
  1739. X        ourarray[nentries] = (char *) malloc(DIRSIZE(entry) + 1);
  1740. X        null_ncpy(ourarray[nentries], entry->d_name, (int) DIRSIZE(entry));
  1741. X        nentries++;
  1742. X    }
  1743. X    closedir(dirp);
  1744. X    if ((nentries + 1) != nalloc)
  1745. X        ourarray = (char **) realloc((char *) ourarray,
  1746. X                    ((nentries + 1) * sizeof (char *)));
  1747. X    if (sorter != 0)
  1748. X        qsort((char *) ourarray, nentries, sizeof (char **), sorter);
  1749. X    *nmptr = ourarray;
  1750. X    ourarray[nentries] = 0;        /* guaranteed 0 pointer */
  1751. X
  1752. X    return nentries;
  1753. X}
  1754. X
  1755. Xfreedir(nmptr, nentries)
  1756. Xchar    ***nmptr;
  1757. X{
  1758. X    char    **ourarray = *nmptr;
  1759. X
  1760. X    while (--nentries >= 0)
  1761. X        free(*ourarray++);
  1762. X    free((char *) *nmptr);
  1763. X    *nmptr = 0;
  1764. X}
  1765. X
  1766. Xalphacomp(a, b)
  1767. Xchar    **a,
  1768. X    **b;
  1769. X{
  1770. X    return strcmp(*a, *b);
  1771. X}
  1772. X
  1773. X#endif
  1774. @//E*O*F scandir.c//
  1775. if test 2708 -ne "`wc -c <'scandir.c'`"; then
  1776.     echo shar: error transmitting "'scandir.c'" '(should have been 2708 characters)'
  1777. fi
  1778. fi # end of overwriting check
  1779. echo shar: extracting "'screen.c'" '(17553 characters)'
  1780. if test -f 'screen.c' ; then 
  1781.   echo shar: will not over-write existing file "'screen.c'"
  1782. else
  1783. sed 's/^X//' >screen.c <<'@//E*O*F screen.c//'
  1784. X/************************************************************************
  1785. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1786. X * provided to you without charge, and with no warranty.  You may give  *
  1787. X * away copies of JOVE, including sources, provided that this notice is *
  1788. X * included in all the files.                                           *
  1789. X ************************************************************************/
  1790. X
  1791. X#include "jove.h"
  1792. X#include "io.h"
  1793. X#include "ctype.h"
  1794. X#include "termcap.h"
  1795. X
  1796. Xextern int    BufSize;
  1797. X
  1798. Xint    OkayAbort,
  1799. X    tabstop = 8;
  1800. X
  1801. Xint    (*TTins_line)(),
  1802. X    (*TTdel_line)();
  1803. X
  1804. Xstruct scrimage
  1805. X    *DesiredScreen = 0,
  1806. X    *PhysScreen = 0;
  1807. X
  1808. Xstruct screenline    *Screen = 0,    /* the screen (a bunch of screenline) */
  1809. X            *Savelines = 0,    /* another bunch (LI of them) */
  1810. X            *Curline = 0;    /* current line */
  1811. Xchar    *cursor,            /* offset into current Line */
  1812. X    *cursend;
  1813. X
  1814. Xint    CapCol,
  1815. X    CapLine,
  1816. X
  1817. X    i_line,
  1818. X    i_col;
  1819. X
  1820. Xmake_scr()
  1821. X{
  1822. X    register int    i;
  1823. X    register struct screenline    *ns;
  1824. X    register char    *nsp;
  1825. X
  1826. X#ifdef RESHAPING
  1827. X    /* In case we are RESHAPING the window! */
  1828. X    if (DesiredScreen)
  1829. X        free((char *) DesiredScreen);
  1830. X    if (PhysScreen)
  1831. X        free((char *) PhysScreen);
  1832. X    if (Savelines)
  1833. X        free((char *) Savelines);
  1834. X    if (Screen) {
  1835. X        free(Screen->s_line);    /* free all the screen data */
  1836. X        free((char *) Screen);
  1837. X    }
  1838. X#endif RESHAPING
  1839. X
  1840. X    DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  1841. X    PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
  1842. X
  1843. X    Savelines = (struct screenline *)
  1844. X            malloc((unsigned) LI * sizeof(struct screenline));
  1845. X    ns = Screen = (struct screenline *)
  1846. X            malloc((unsigned) LI * sizeof(struct screenline));
  1847. X
  1848. X    nsp = (char *) malloc((unsigned)CO * LI);
  1849. X    if (nsp == 0) {
  1850. X        printf("\n\rCannot malloc screen!\n");
  1851. X        finish(1);
  1852. X    }
  1853. X
  1854. X    for (i = 0; i < LI; i++) {
  1855. X        ns->s_line = nsp;
  1856. X        nsp += CO;
  1857. X        ns->s_length = nsp - 1;        /* End of Line */
  1858. X        ns++;
  1859. X    }
  1860. X    cl_scr(0);
  1861. X}
  1862. X
  1863. Xclrline(cp1, cp2)
  1864. Xregister char    *cp1,
  1865. X        *cp2;
  1866. X{
  1867. X    while (cp1 <= cp2)
  1868. X        *cp1++ = ' ';
  1869. X}
  1870. X
  1871. X#define sputc(c)    ((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++))
  1872. X#define soutputc(c)    if (--n <= 0) break; else sputc(c)
  1873. X
  1874. Xcl_eol()
  1875. X{
  1876. X    if (cursor > cursend)
  1877. X        return;
  1878. X
  1879. X    if (cursor < Curline->s_length) {
  1880. X        if (CE) {
  1881. X            Placur(i_line, i_col);
  1882. X            putpad(CE, 1);
  1883. X            clrline(cursor, Curline->s_length);
  1884. X        } else {
  1885. X        /* Ugh.  The slow way for dumb terminals. */
  1886. X            register char *savecp = cursor;
  1887. X
  1888. X            while (cursor <= Curline->s_length)
  1889. X                sputc(' ');
  1890. X            cursor = savecp;
  1891. X        }
  1892. X        Curline->s_length = cursor;
  1893. X    }
  1894. X}
  1895. X
  1896. Xcl_scr(doit)
  1897. X{
  1898. X    register int    i;
  1899. X    register struct screenline    *sp = Screen;
  1900. X
  1901. X    for (i = 0; i < LI; i++, sp++) {
  1902. X        clrline(sp->s_line, sp->s_length);
  1903. X        sp->s_length = sp->s_line;
  1904. X        PhysScreen[i].s_id = 0;
  1905. X    }
  1906. X    if (doit) {
  1907. X        putpad(CL, LI);
  1908. X        CapCol = CapLine = 0;
  1909. X        UpdMesg++;
  1910. X    }
  1911. X}
  1912. X
  1913. X#ifdef ID_CHAR
  1914. Xextern int    IN_INSmode;
  1915. X#endif
  1916. X
  1917. X/* Output one character (if necessary) at the current position */
  1918. X
  1919. Xdosputc(c)
  1920. Xregister char    c;
  1921. X{
  1922. X    if (*cursor != c) {
  1923. X#ifdef ID_CHAR
  1924. X        if (IN_INSmode)
  1925. X            INSmode(0);
  1926. X#endif
  1927. X        if (i_line != CapLine || i_col != CapCol)
  1928. X            Placur(i_line, i_col);
  1929. X        if (UL && (c & 0177) == '_' && (*cursor & 0177) != ' ')
  1930. X            putstr(" \b");        /* Erase so '_' looks right. */
  1931. X        *cursor++ = c;
  1932. X        putchar(c & 0177);
  1933. X        CapCol++;
  1934. X        i_col++;
  1935. X    } else {
  1936. X        cursor++;
  1937. X        i_col++;
  1938. X    }
  1939. X}
  1940. X
  1941. X/* Write `line' at the current position of `cursor'.  Stop when we
  1942. X   reach the end of the screen.  Aborts if there is a character
  1943. X   waiting.  */
  1944. X
  1945. Xswrite(line, inversep, abortable)
  1946. Xregister char    *line;
  1947. Xregister int    abortable;
  1948. X{
  1949. X    register int    c;
  1950. X    int    col = i_col,
  1951. X        aborted = 0;
  1952. X    register int    n = cursend - cursor;
  1953. X    int    or_byte = inversep ? 0200 : 0,
  1954. X        thebyte;
  1955. X
  1956. X    if (n <= 0)
  1957. X        return 1;
  1958. X
  1959. X    OkayAbort = 0;
  1960. X    while (c = *line++) {
  1961. X        if (abortable && OkayAbort) {
  1962. X            OkayAbort = NO;
  1963. X            if (InputPending = charp()) {
  1964. X                aborted = 1;
  1965. X                break;
  1966. X            }
  1967. X        }
  1968. X        if (c == '\t') {
  1969. X            int    nchars;
  1970. X
  1971. X            nchars = (tabstop - (col % tabstop));
  1972. X            col += nchars;
  1973. X
  1974. X            thebyte = (' ' | or_byte);
  1975. X            while (nchars--)
  1976. X                soutputc(thebyte);
  1977. X            if (n <= 0)
  1978. X                break;
  1979. X        } else if (isctrl(c)) {
  1980. X            thebyte = ('^' | or_byte);
  1981. X            soutputc(thebyte);
  1982. X            thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
  1983. X            soutputc(thebyte);
  1984. X            col += 2;
  1985. X        } else {
  1986. X            thebyte = (c | or_byte);
  1987. X            soutputc(thebyte);
  1988. X            col++;
  1989. X        }
  1990. X    }
  1991. X    if (n <= 0) {
  1992. X        if ((*line == '\0') && (c != '\t') && !isctrl(c))
  1993. X            sputc(c|or_byte);
  1994. X        else
  1995. X            sputc('!'|or_byte);
  1996. X    }
  1997. X    if (cursor > Curline->s_length)
  1998. X        Curline->s_length = cursor;
  1999. X    return !aborted;
  2000. X}
  2001. X
  2002. X/* This is for writing a buffer line to the screen.  This is to
  2003. X   minimize the amount of copying from one buffer to another buffer.
  2004. X   This gets the info directly from the disk buffers. */
  2005. X
  2006. XBufSwrite(linenum)
  2007. X{
  2008. X    char    *bp;
  2009. X    register int    n = cursend - cursor,
  2010. X            col = 0,
  2011. X            c;
  2012. X    int    StartCol = DesiredScreen[linenum].s_offset,
  2013. X        visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
  2014. X        aborted = 0;
  2015. X
  2016. X    bp = lcontents(DesiredScreen[linenum].s_lp);
  2017. X    if (*bp) for (;;) {
  2018. X        if (col >= StartCol) {
  2019. X            DesiredScreen[linenum].s_offset = col;
  2020. X            break;
  2021. X        }
  2022. X
  2023. X        c = *bp++ & 0177;
  2024. X        if (c == '\t')
  2025. X            col += (tabstop - (col % tabstop));
  2026. X        else if (isctrl(c))
  2027. X            col += 2;
  2028. X        else
  2029. X            col++;
  2030. X    }
  2031. X
  2032. X    OkayAbort = 0;
  2033. X    while (c = (*bp++ & 0177)) {
  2034. X        if (OkayAbort) {
  2035. X            OkayAbort = NO;
  2036. X            if (InputPending = charp()) {
  2037. X                aborted = 1;
  2038. X                break;
  2039. X            }
  2040. X        }
  2041. X        if (c == '\t') {
  2042. X            int    nchars = (tabstop - (col % tabstop));
  2043. X
  2044. X            col += nchars;
  2045. X            if (visspace) {
  2046. X                soutputc('>');
  2047. X                nchars--;
  2048. X            }
  2049. X            while (--nchars >= 0)
  2050. X                soutputc(' ');
  2051. X            if (n <= 0)
  2052. X                break;
  2053. X        } else if (isctrl(c)) {
  2054. X            soutputc('^');
  2055. X            soutputc((c == '\177') ? '?' : c + '@');
  2056. X            col += 2;
  2057. X        } else {
  2058. X            if (c == ' ' && visspace)
  2059. X                c = '_';
  2060. X            soutputc(c);
  2061. X            col++;
  2062. X        }
  2063. X    }
  2064. X    if (n <= 0) {
  2065. X        if ((*bp == '\0') && (c != '\t') && !isctrl(c))
  2066. X            sputc(c);
  2067. X        else
  2068. X            sputc('!');
  2069. X    }
  2070. X    if (cursor > Curline->s_length)
  2071. X        Curline->s_length = cursor;
  2072. X    return !aborted;        /* Didn't abort */
  2073. X}
  2074. X
  2075. Xi_set(nline, ncol)
  2076. Xregister int    nline,
  2077. X        ncol;
  2078. X{
  2079. X    Curline = &Screen[nline];
  2080. X    cursor = Curline->s_line + ncol;
  2081. X    cursend = &Curline->s_line[CO - 1];
  2082. X    i_line = nline;
  2083. X    i_col = ncol;
  2084. X}
  2085. X
  2086. X/* Insert `num' lines a top, but leave all the lines BELOW `bottom'
  2087. X   alone (at least they won't look any different when we are done).
  2088. X   This changes the screen array AND does the physical changes. */
  2089. X
  2090. Xv_ins_line(num, top, bottom)
  2091. X{
  2092. X    register int    i;
  2093. X
  2094. X    /* Save the screen pointers. */
  2095. X
  2096. X    for(i = 0; i < num && top + i <= bottom; i++)
  2097. X        Savelines[i] = Screen[bottom - i];
  2098. X
  2099. X    /* Num number of bottom lines will be lost.
  2100. X       Copy everything down num number of times. */
  2101. X
  2102. X    for (i = bottom; i > top && i-num >= 0; i--)
  2103. X        Screen[i] = Screen[i - num];
  2104. X
  2105. X    /* Restore the saved ones, making them blank. */
  2106. X
  2107. X    for (i = 0; i < num; i++) {
  2108. X        Screen[top + i] = Savelines[i];
  2109. X        clrline(Screen[top + i].s_line, Screen[top + i].s_length);
  2110. X        Screen[top + i].s_length = Screen[top + i].s_line;
  2111. X    }
  2112. X
  2113. X    (*TTins_line)(top, bottom, num);
  2114. X}
  2115. X
  2116. X/* Delete `num' lines starting at `top' leaving the lines below `bottom'
  2117. X   alone.  This updates the internal image as well as the physical image.  */
  2118. X
  2119. Xv_del_line(num, top, bottom)
  2120. X{
  2121. X    register int    i,
  2122. X            bot;
  2123. X
  2124. X    bot = bottom;
  2125. X
  2126. X    /* Save the lost lines. */
  2127. X
  2128. X    for (i = 0; i < num && top + i <= bottom; i++)
  2129. X        Savelines[i] = Screen[top + i];
  2130. X
  2131. X    /* Copy everything up num number of lines. */
  2132. X
  2133. X    for (i = top; num + i <= bottom; i++)
  2134. X        Screen[i] = Screen[i + num];
  2135. X
  2136. X    /* Restore the lost ones, clearing them. */
  2137. X
  2138. X    for (i = 0; i < num; i++) {
  2139. X        Screen[bottom - i] = Savelines[i];
  2140. X        clrline(Screen[bot].s_line, Screen[bot].s_length);
  2141. X        Screen[bot].s_length = Screen[bot].s_line;
  2142. X        bot--;
  2143. X    }
  2144. X
  2145. X    (*TTdel_line)(top, bottom, num);
  2146. X}
  2147. X
  2148. X
  2149. X/* The cursor optimization happens here.  You may decide that this
  2150. X   is going too far with cursor optimization, or perhaps it should
  2151. X   limit the amount of checking to when the output speed is slow.
  2152. X   What ever turns you on ...   */
  2153. X
  2154. Xprivate struct cursaddr {
  2155. X    int    c_numchars,
  2156. X        (*c_proc)();
  2157. X};
  2158. X
  2159. Xprivate char    *Cmstr;
  2160. Xprivate struct cursaddr    *HorMin,
  2161. X            *VertMin,
  2162. X            *DirectMin;
  2163. X
  2164. Xprivate ForMotion(),
  2165. X    ForTab(),
  2166. X    BackMotion(),
  2167. X    RetTab(),
  2168. X    DownMotion(),
  2169. X    UpMotion(),
  2170. X    GoDirect(),
  2171. X    HomeGo(),
  2172. X    BottomUp();
  2173. X    
  2174. X
  2175. Xprivate struct cursaddr    WarpHor[] = {
  2176. X    0,    ForMotion,
  2177. X    0,    ForTab,
  2178. X    0,    BackMotion,
  2179. X    0,    RetTab
  2180. X};
  2181. X
  2182. Xprivate struct cursaddr    WarpVert[] = {
  2183. X    0,    DownMotion,
  2184. X    0,    UpMotion
  2185. X};
  2186. X
  2187. Xprivate struct cursaddr    WarpDirect[] = {
  2188. X    0,    GoDirect,
  2189. X    0,    HomeGo,
  2190. X    0,    BottomUp
  2191. X};
  2192. X
  2193. X#undef    FORWARD
  2194. X#define    FORWARD        0    /* Move forward */
  2195. X#define FORTAB        1    /* Forward using tabs */
  2196. X#undef    BACKWARD
  2197. X#define    BACKWARD    2    /* Move backward */
  2198. X#define RETFORWARD    3    /* Beginning of line and then tabs */
  2199. X#define NUMHOR        4
  2200. X
  2201. X#define DOWN        0    /* Move down */
  2202. X#define UPMOVE        1    /* Move up */
  2203. X#define NUMVERT        2
  2204. X
  2205. X#define DIRECT        0    /* Using CM */
  2206. X#define HOME        1    /* HOME    */
  2207. X#define LOWER        2    /* Lower Line */
  2208. X#define NUMDIRECT    3
  2209. X
  2210. X#define    home()        Placur(0, 0)
  2211. X#define LowLine()    putpad(LL, 1), CapLine = ILI, CapCol = 0
  2212. X#define PrintHo()    putpad(HO, 1), CapLine = CapCol = 0
  2213. X
  2214. Xint    phystab = 8;
  2215. X
  2216. Xprivate
  2217. XGoDirect(line, col)
  2218. Xregister int    line,
  2219. X        col;
  2220. X{
  2221. X    putpad(Cmstr, 1);
  2222. X    CapLine = line;
  2223. X    CapCol = col;
  2224. X}
  2225. X
  2226. Xprivate
  2227. XRetTab(col)
  2228. Xregister int    col;
  2229. X{
  2230. X    putchar('\r');
  2231. X    CapCol = 0;
  2232. X    ForTab(col);
  2233. X}
  2234. X
  2235. Xprivate
  2236. XHomeGo(line, col)
  2237. X{
  2238. X    PrintHo();
  2239. X    DownMotion(line);
  2240. X    ForTab(col);
  2241. X}
  2242. X
  2243. Xprivate
  2244. XBottomUp(line, col)
  2245. Xregister int    line,
  2246. X        col;
  2247. X{
  2248. X    LowLine();
  2249. X    UpMotion(line);
  2250. X    ForTab(col);
  2251. X}
  2252. X
  2253. X/* Tries to move forward using tabs (if possible).  It tabs to the
  2254. X   closest tabstop which means it may go past 'destcol' and backspace
  2255. X   to it. */
  2256. X
  2257. Xprivate
  2258. XForTab(destcol)
  2259. Xint    destcol;
  2260. X{
  2261. X    register int    tabgoal,
  2262. X            ntabs,
  2263. X            tabstp = phystab;
  2264. X
  2265. X    if (TABS && (tabstp > 0)) {
  2266. X        tabgoal = destcol + (tabstp / 2);
  2267. X        tabgoal -= (tabgoal % tabstp);
  2268. X
  2269. X        /* Don't tab to last place or else it is likely to screw up. */
  2270. X        if (tabgoal >= CO)
  2271. X            tabgoal -= tabstp;
  2272. X
  2273. X        ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
  2274. X        while (--ntabs >= 0)
  2275. X            putchar('\t');
  2276. X        CapCol = tabgoal;
  2277. X    }
  2278. X    if (CapCol > destcol)
  2279. X        BackMotion(destcol);
  2280. X    else if (CapCol < destcol)
  2281. X        ForMotion(destcol);
  2282. X}
  2283. X
  2284. Xprivate
  2285. XForMotion(destcol)
  2286. Xregister int    destcol;
  2287. X{
  2288. X    register int    nchars = destcol - CapCol;
  2289. X    register char    *cp = &Screen[CapLine].s_line[CapCol];
  2290. X
  2291. X    while (--nchars >= 0)
  2292. X        putchar(*cp++ & 0177);
  2293. X    CapCol = destcol;
  2294. X}
  2295. X
  2296. Xprivate
  2297. XBackMotion(destcol)
  2298. Xregister int    destcol;
  2299. X{
  2300. X    register int    nchars = CapCol - destcol;
  2301. X
  2302. X    if (BC)
  2303. X        while (--nchars >= 0)
  2304. X            putpad(BC, 1);
  2305. X    else
  2306. X        while (--nchars >= 0)
  2307. X            putchar('\b');
  2308. X    CapCol = destcol;
  2309. X}
  2310. X
  2311. Xprivate
  2312. XDownMotion(destline)
  2313. Xregister int    destline;
  2314. X{
  2315. X    register int    nlines = destline - CapLine;
  2316. X
  2317. X    while (--nlines >= 0)
  2318. X        putchar('\n');
  2319. X    CapLine = destline;
  2320. X}
  2321. X
  2322. Xprivate
  2323. XUpMotion(destline)
  2324. Xregister int    destline;
  2325. X{
  2326. X    register int    nchars = CapLine - destline;
  2327. X
  2328. X    while (--nchars >= 0)
  2329. X        putpad(UP, 1);
  2330. X    CapLine = destline;
  2331. X}
  2332. X
  2333. X#ifdef ID_CHAR
  2334. Xstatic int    EIlen;
  2335. X#endif
  2336. Xextern int    IMlen;
  2337. X
  2338. XInitCM()
  2339. X{
  2340. X    HOlen = HO ? strlen(HO) : 1000;
  2341. X    LLlen = LL ? strlen(LL) : 1000;
  2342. X    UPlen = UP ? strlen(UP) : 1000;
  2343. X#ifdef ID_CHAR
  2344. X    if (EI)
  2345. X        EIlen = strlen(EI);
  2346. X#endif
  2347. X}
  2348. X
  2349. XPlacur(line, col)
  2350. X{
  2351. X    int    dline,        /* Number of lines to move */
  2352. X        dcol;        /* Number of columns to move */
  2353. X    register int    best,
  2354. X            i;
  2355. X    register struct cursaddr    *cp;
  2356. X    int    xtracost = 0;    /* Misc addition to cost. */
  2357. X
  2358. X#define CursMin(which,addrs,max) \
  2359. X    for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \
  2360. X        if (cp->c_numchars < addrs[best].c_numchars) \
  2361. X            best = i; \
  2362. X    which = &addrs[best];
  2363. X
  2364. X    if (line == CapLine && col == CapCol)
  2365. X        return;        /* We are already there. */
  2366. X
  2367. X    dline = line - CapLine;
  2368. X    dcol = col - CapCol;
  2369. X#ifdef ID_CHAR
  2370. X    if (IN_INSmode && MI)
  2371. X        xtracost = EIlen + IMlen;
  2372. X    /* If we're already in insert mode, it is likely that we will
  2373. X       want to be in insert mode again, after the insert. */
  2374. X#endif
  2375. X
  2376. X    /* Number of characters to move horizontally for each case.
  2377. X       1: Just move forward by typing the right character on the screen.
  2378. X       2: Print the correct number of back spaces.
  2379. X       3: Try tabbing to the correct place.
  2380. X       4: Try going to the beginning of the line, and then tab. */
  2381. X
  2382. X    if (dcol == 1 || dcol == 0) {        /* Most common case. */
  2383. X        HorMin = &WarpHor[FORWARD];
  2384. X        HorMin->c_numchars = dcol + xtracost;
  2385. X    } else {
  2386. X        WarpHor[FORWARD].c_numchars = dcol >= 0 ? dcol + xtracost : 1000;
  2387. X        WarpHor[BACKWARD].c_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
  2388. X        WarpHor[FORTAB].c_numchars = dcol >= 0 && TABS ?
  2389. X                ForNum(CapCol, col) + xtracost : 1000;
  2390. X        WarpHor[RETFORWARD].c_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
  2391. X
  2392. X        /* Which is the shortest of the bunch */
  2393. X
  2394. X        CursMin(HorMin, WarpHor, NUMHOR);
  2395. X    }
  2396. X
  2397. X    /* Moving vertically is more simple. */
  2398. X
  2399. X    WarpVert[DOWN].c_numchars = dline >= 0 ? dline : 1000;
  2400. X    WarpVert[UPMOVE].c_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
  2401. X
  2402. X    /* Which of these is simpler */
  2403. X    CursMin(VertMin, WarpVert, NUMVERT);
  2404. X
  2405. X    /* Homing first and lowering first are considered 
  2406. X       direct motions.
  2407. X       Homing first's total is the sum of the cost of homing
  2408. X       and the sum of tabbing (if possible) to the right. */
  2409. X    
  2410. X    if (VertMin->c_numchars + HorMin->c_numchars <= 3) {
  2411. X        DirectMin = &WarpDirect[DIRECT];    /* A dummy ... */
  2412. X        DirectMin->c_numchars = 100;
  2413. X    } else {
  2414. X        WarpDirect[DIRECT].c_numchars = CM ?
  2415. X                strlen(Cmstr = tgoto(CM, col, line)) : 1000;
  2416. X        WarpDirect[HOME].c_numchars = HOlen + line +
  2417. X                WarpHor[RETFORWARD].c_numchars;
  2418. X        WarpDirect[LOWER].c_numchars = LLlen + ((ILI - line) * UPlen) +
  2419. X                WarpHor[RETFORWARD].c_numchars;
  2420. X        CursMin(DirectMin, WarpDirect, NUMDIRECT);
  2421. X    }
  2422. X
  2423. X    if (HorMin->c_numchars + VertMin->c_numchars < DirectMin->c_numchars) {
  2424. X        if (line != CapLine)
  2425. X            (*VertMin->c_proc)(line);
  2426. X        if (col != CapCol) {
  2427. X#ifdef ID_CHAR
  2428. X            if (IN_INSmode)    /* We may use real characters ... */
  2429. X                INSmode(0);
  2430. X#endif
  2431. X            (*HorMin->c_proc)(col);
  2432. X        }
  2433. X    } else {
  2434. X#ifdef ID_CHAR
  2435. X        if (IN_INSmode && !MI)
  2436. X            INSmode(0);
  2437. X#endif
  2438. X        (*DirectMin->c_proc)(line, col);
  2439. X    }
  2440. X}
  2441. X
  2442. X#define abs(x)    ((x) >= 0 ? (x) : -(x))
  2443. X
  2444. XForNum(from, to)
  2445. Xregister int    from;
  2446. X{
  2447. X    register int    tabgoal,
  2448. X            tabstp = phystab;
  2449. X    int        numchars = 0;
  2450. X
  2451. X    if (from >= to)
  2452. X        return from - to;
  2453. X    if (TABS && (tabstp > 0)) {
  2454. X        tabgoal = to + (tabstp / 2);
  2455. X        tabgoal -= (tabgoal % tabstp);
  2456. X        if (tabgoal >= CO)
  2457. X            tabgoal -= tabstp;
  2458. X        numchars = (tabgoal / tabstop) - (from / tabstp);
  2459. X        from = tabgoal;
  2460. X    }
  2461. X    return numchars + abs(from - to);
  2462. X}
  2463. X
  2464. X#ifdef WIRED_TERMS
  2465. X
  2466. XBGi_lines(top, bottom, num)
  2467. X{
  2468. X    printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
  2469. X    CapCol = CapLine = 0;
  2470. X}
  2471. X
  2472. XSUNi_lines(top, bottom, num)
  2473. X{
  2474. X    Placur(bottom - num + 1, 0);
  2475. X    printf("\033[%dM", num);
  2476. X    Placur(top, 0);
  2477. X    printf("\033[%dL", num);
  2478. X}
  2479. X
  2480. XC100i_lines(top, bottom, num)
  2481. X{
  2482. X    if (num <= 1) {
  2483. X        GENi_lines(top, bottom, num);
  2484. X        return;
  2485. X    }
  2486. X    printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  2487. X    CapLine = CapCol = 0;
  2488. X    Placur(top, 0);
  2489. X    while (num--)
  2490. X        putpad(AL, ILI - CapLine);
  2491. X    printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  2492. X    CapLine = CapCol = 0;
  2493. X}
  2494. X
  2495. X#endif WIRED_TERMS
  2496. X
  2497. XGENi_lines(top, bottom, num)
  2498. X{
  2499. X    register int    i;
  2500. X
  2501. X    if (CS) {
  2502. X        putpad(tgoto(CS, bottom, top));
  2503. X        CapCol = CapLine = 0;
  2504. X        Placur(top, 0);
  2505. X        for (i = 0; i < num; i++)
  2506. X            putpad(SR, bottom - top);
  2507. X        putpad(tgoto(CS, ILI, 0));
  2508. X        CapCol = CapLine = 0;
  2509. X    } else {
  2510. X        Placur(bottom - num + 1, 0);
  2511. X        if (M_DL && (num > 1)) {
  2512. X            char    minibuf[16];
  2513. X
  2514. X            sprintf(minibuf, M_DL, num);
  2515. X            putpad(minibuf, ILI - CapLine);
  2516. X        } else {
  2517. X            for (i = 0; i < num; i++)
  2518. X                putpad(DL, ILI - CapLine);
  2519. X        }
  2520. X        Placur(top, 0);
  2521. X        if (M_AL && (num > 1)) {
  2522. X            char    minibuf[16];
  2523. X
  2524. X            sprintf(minibuf, M_AL, num);
  2525. X            putpad(minibuf, ILI - CapLine);
  2526. X        } else {
  2527. X            for (i = 0; i < num; i++)
  2528. X                putpad(AL, ILI - CapLine);
  2529. X        }
  2530. X    }
  2531. X}
  2532. X
  2533. X#ifdef WIRED_TERMS
  2534. X
  2535. XBGd_lines(top, bottom, num)
  2536. X{
  2537. X    printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
  2538. X    CapCol = CapLine = 0;
  2539. X}
  2540. X
  2541. XSUNd_lines(top, bottom, num)
  2542. X{
  2543. X    Placur(top, 0);
  2544. X    printf("\033[%dM", num);
  2545. X    Placur(bottom + 1 - num, 0);
  2546. X    printf("\033[%dL", num);
  2547. X}
  2548. X
  2549. XC100d_lines(top, bottom, num)
  2550. X{
  2551. X    if (num <= 1) {
  2552. X        GENd_lines(top, bottom, num);
  2553. X        return;
  2554. X    }
  2555. X    printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
  2556. X    CapLine = CapCol = 0;
  2557. X    Placur(top, 0);
  2558. X    while (num--)
  2559. X        putpad(DL, ILI - CapLine);
  2560. X    printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
  2561. X    CapLine = CapCol = 0;
  2562. X}
  2563. X
  2564. X#endif WIRED_TERMS
  2565. X
  2566. XGENd_lines(top, bottom, num)
  2567. X{
  2568. X    register int    i;
  2569. X
  2570. X    if (CS) {
  2571. X        putpad(tgoto(CS, bottom, top));
  2572. X        CapCol = CapLine = 0;
  2573. X        Placur(bottom, 0);
  2574. X        for (i = 0; i < num; i++)
  2575. X            putpad(SF, bottom - top);
  2576. X        putpad(tgoto(CS, ILI, 0));
  2577. X        CapCol = CapLine = 0;
  2578. X    } else {
  2579. X        Placur(top, 0);
  2580. X        if (M_DL && (num > 1)) {
  2581. X            char    minibuf[16];
  2582. X
  2583. X            sprintf(minibuf, M_DL, num);
  2584. X            putpad(minibuf, ILI - top);
  2585. X        } else {
  2586. X            for (i = 0; i < num; i++)
  2587. X                putpad(DL, ILI - top);
  2588. X        }
  2589. X        Placur(bottom + 1 - num, 0);
  2590. X        if (M_AL && (num > 1)) {
  2591. X            char    minibuf[16];
  2592. X
  2593. X            sprintf(minibuf, M_AL, num);
  2594. X            putpad(minibuf, ILI - CapLine);
  2595. X        } else {
  2596. X            for (i = 0; i < num; i++)
  2597. X                putpad(AL, ILI - CapLine);
  2598. X        }
  2599. X    }
  2600. X}
  2601. X
  2602. Xstruct ID_lookup {
  2603. X    char    *ID_name;
  2604. X    int    (*I_proc)();    /* proc to insert lines */
  2605. X    int    (*D_proc)();    /* proc to delete lines */
  2606. X} ID_trms[] = {
  2607. X    "generic",    GENi_lines,    GENd_lines,    /* This should stay here */
  2608. X#ifdef WIRED_TERMS
  2609. X    "sun",        SUNi_lines,    SUNd_lines,
  2610. X    "bg",        BGi_lines,    BGd_lines,
  2611. X    "c1",        C100i_lines,    C100d_lines,
  2612. X#endif WIRED_TERMS
  2613. X    0,        0,        0
  2614. X};
  2615. X
  2616. XIDline_setup(tname)
  2617. Xchar    *tname;
  2618. X{
  2619. X    register struct ID_lookup    *idp;
  2620. X
  2621. X    for (idp = &ID_trms[1]; idp->ID_name; idp++)
  2622. X        if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
  2623. X            break;
  2624. X    if (idp->ID_name == 0)
  2625. X        idp = &ID_trms[0];
  2626. X    TTins_line = idp->I_proc;
  2627. X    TTdel_line = idp->D_proc;
  2628. X}
  2629. @//E*O*F screen.c//
  2630. if test 17553 -ne "`wc -c <'screen.c'`"; then
  2631.     echo shar: error transmitting "'screen.c'" '(should have been 17553 characters)'
  2632. fi
  2633. fi # end of overwriting check
  2634. echo shar: extracting "'teachjove.c'" '(1052 characters)'
  2635. if test -f 'teachjove.c' ; then 
  2636.   echo shar: will not over-write existing file "'teachjove.c'"
  2637. else
  2638. sed 's/^X//' >teachjove.c <<'@//E*O*F teachjove.c//'
  2639. X/************************************************************************
  2640. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2641. X * provided to you without charge, and with no warranty.  You may give  *
  2642. X * away copies of JOVE, including sources, provided that this notice is *
  2643. X * included in all the files.                                           *
  2644. X ************************************************************************/
  2645. X
  2646. X#include <sys/types.h>
  2647. X#include <sys/file.h>
  2648. X
  2649. X#ifndef TEACHJOVE
  2650. X#    define TEACHJOVE    "/usr/lib/jove/teach-jove"
  2651. X#endif
  2652. X
  2653. X#ifndef W_OK
  2654. X#   define W_OK    2
  2655. X#   define F_OK    0
  2656. X#endif
  2657. X
  2658. Xextern char    *getenv();
  2659. X
  2660. Xmain()
  2661. X{
  2662. X    char    cmd[256],
  2663. X        fname[256],
  2664. X        *home;
  2665. X
  2666. X    if ((home = getenv("HOME")) == 0) {
  2667. X        printf("teachjove: cannot find your home!\n");
  2668. X        exit(-1);
  2669. X    }
  2670. X    (void) sprintf(fname, "%s/teach-jove", home);
  2671. X    if (access(fname, F_OK) != 0) {
  2672. X        (void) sprintf(cmd, "cp %s %s", TEACHJOVE, fname);
  2673. X        system(cmd);
  2674. X    }
  2675. X    (void) execlp("jove", "teachjove", fname, (char *) 0);
  2676. X    printf("teachjove: cannot execl jove!\n");
  2677. X}
  2678. X
  2679. @//E*O*F teachjove.c//
  2680. if test 1052 -ne "`wc -c <'teachjove.c'`"; then
  2681.     echo shar: error transmitting "'teachjove.c'" '(should have been 1052 characters)'
  2682. fi
  2683. fi # end of overwriting check
  2684. echo shar: extracting "'tune.template'" '(882 characters)'
  2685. if test -f 'tune.template' ; then 
  2686.   echo shar: will not over-write existing file "'tune.template'"
  2687. else
  2688. sed 's/^X//' >tune.template <<'@//E*O*F tune.template//'
  2689. X/************************************************************************
  2690. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2691. X * provided to you without charge, and with no warranty.  You may give  *
  2692. X * away copies of JOVE, including sources, provided that this notice is *
  2693. X * included in all the files.                                           *
  2694. X ************************************************************************/
  2695. X
  2696. X#define NOEXTERNS
  2697. X
  2698. X#include "tune.h"
  2699. X
  2700. Xchar    TmpFilePath[128] = "TMPDIR";
  2701. X
  2702. Xchar    *d_tempfile = "joveXXXXXX",    /* buffer lines go here */
  2703. X    *p_tempfile = "jrecXXXXXX",    /* line pointers go here */
  2704. X    *Recover = "LIBDIR/recover",
  2705. X    *CmdDb = "LIBDIR/cmds.doc",
  2706. X        /* copy of "cmds.doc" lives in the doc subdirectory */
  2707. X
  2708. X    *Joverc = "LIBDIR/.joverc",
  2709. X
  2710. X#ifdef PIPEPROCS
  2711. X    *Portsrv = "LIBDIR/portsrv",
  2712. X#endif
  2713. X
  2714. X    Shell[128] = "SHELL",
  2715. X    ShFlags[16] = "-c";
  2716. @//E*O*F tune.template//
  2717. if test 882 -ne "`wc -c <'tune.template'`"; then
  2718.     echo shar: error transmitting "'tune.template'" '(should have been 882 characters)'
  2719. fi
  2720. fi # end of overwriting check
  2721. echo shar: extracting "'version.c'" '(473 characters)'
  2722. if test -f 'version.c' ; then 
  2723.   echo shar: will not over-write existing file "'version.c'"
  2724. else
  2725. sed 's/^X//' >version.c <<'@//E*O*F version.c//'
  2726. X/************************************************************************
  2727. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2728. X * provided to you without charge, and with no warranty.  You may give  *
  2729. X * away copies of JOVE, including sources, provided that this notice is *
  2730. X * included in all the files.                                           *
  2731. X ************************************************************************/
  2732. X
  2733. Xchar    *version = "4.6.1.4";
  2734. @//E*O*F version.c//
  2735. if test 473 -ne "`wc -c <'version.c'`"; then
  2736.     echo shar: error transmitting "'version.c'" '(should have been 473 characters)'
  2737. fi
  2738. fi # end of overwriting check
  2739. echo shar: "End of archive 7 (of 13)."
  2740. cp /dev/null ark7isdone
  2741. DONE=true
  2742. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
  2743.     if test -f ark${I}isdone; then
  2744.         echo "You have run archive ${I}."
  2745.     else
  2746.         echo "You still need to run archive ${I}."
  2747.         DONE=false
  2748.     fi
  2749. done
  2750. case $DONE in
  2751.     true)
  2752.         echo "You have run all 13 archives."
  2753.         echo 'Now read the README and Makefile.'
  2754.         ;;
  2755. esac
  2756. ##  End of shell archive.
  2757. exit 0
  2758.